<?php if(! defined('SYSPATH')) exit('No direct script access allowed');
/*
 +----------------------------------------------------------------------+
 | QuickPHP Framework Version 0.10                                      |
 +----------------------------------------------------------------------+
 | Copyright (c) 2010 QuickPHP.net All rights reserved.                 |
 +----------------------------------------------------------------------+
 | Licensed under the Apache License, Version 2.0 (the 'License');      |
 | you may not use this file except in compliance with the License.     |
 | You may obtain a copy of the License at                              |
 | http://www.apache.org/licenses/LICENSE-2.0                           |
 | Unless required by applicable law or agreed to in writing, software  |
 | distributed under the License is distributed on an 'AS IS' BASIS,    |
 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or      |
 | implied. See the License for the specific language governing         |
 | permissions and limitations under the License.                       |
 +----------------------------------------------------------------------+
 | Author: BoPo <ibopo@126.com>                                         |
 +----------------------------------------------------------------------+
*/
/**
 * QuickPHP Encrypt的加/解密类,该类依赖PHP的MCrypt扩展.
 * @see http://php.net/mcrypt
 *
 * @category    QuickPHP
 * @package     Encrypt
 * @author      BoPo <ibopo@126.com>
 * @copyright   Copyright &copy; 2010 QuickPHP
 * @license     http://www.quickphp.net/license/
 * @version     $Id: Encrypt.php 7240 2011-01-22 14:27:59Z bopo $
 */
class QuickPHP_Encrypt
{

    protected static $_instance;

    protected static $rand;

    protected $config = array(
        'key'       => 'K0H@NA+PHP_7hE-SW!FtFraM3w0R|<',
        'mode'      => MCRYPT_MODE_NOFB,
        'cipher'    => MCRYPT_RIJNDAEL_128);

    /**
     * 获得实例方法.
     *
     * @param   array  配置参数
     * @return  Encrypt
     */
    public static function instance(array $config = null)
    {
        if(empty(Encrypt::$_instance))
            Encrypt::$_instance = new Encrypt($config);

        return Encrypt::$_instance;
    }

    /**
     * 构造函数，读取配置和初始化数据
     *
     * @param   array|string 自定义配置或一个配置组名(配置文件中的组),如果为空，则使用默认值
     * @throws  QuickPHP_Exception
     */
    public function __construct(array $config = null)
    {
        if(! defined('MCRYPT_Encrypt'))
            throw new QuickPHP_Exception('encrypt.requires_mcrypt');

        if(! empty($config))
            foreach ($config as $key => $val)
                if(isset($this->config[$key]))
                    $this->config[$key] = $val;

        $size = mcrypt_get_key_size($this->config['cipher'], $this->config['mode']);

        if(strlen($this->config['key']) > $size)
            $this->config['key'] = substr($this->config['key'], 0, $size);

        $this->config['iv_size'] = mcrypt_get_iv_size($this->config['cipher'], $this->config['mode']);
    }

    /**
     * 加密方法.
     *
     * @param   string  需要加密的字符串
     * @return  string  加密后字符串
     */
    public function encode($data)
    {
        if(Encrypt::$rand === NULL)
        {
            if(QuickPHP::$is_windows)
            {
                Encrypt::$rand = MCRYPT_RAND;
            }
            else
            {
                if(defined('MCRYPT_DEV_URANDOM'))
                    Encrypt::$rand = MCRYPT_DEV_URANDOM;
                elseif(defined('MCRYPT_DEV_RANDOM'))
                    Encrypt::$rand = MCRYPT_DEV_RANDOM;
                else
                    Encrypt::$rand = MCRYPT_RAND;
            }
        }

        if(Encrypt::$rand === MCRYPT_RAND)
            mt_srand();

        $iv     = mcrypt_create_iv($this->config['iv_size'], Encrypt::$rand);
        $data   = mcrypt_Encrypt($this->config['cipher'], $this->config['key'], $data, $this->config['mode'], $iv);

        return base64_encode($iv . $data);
    }

    /**
     * 解密方法.
     *
     * @param   string  需要解密的字符串
     * @return  string  解密后字符串
     */
    public function decode($data)
    {
        $data   = base64_decode($data);
        $iv     = substr($data, 0, $this->config['iv_size']);
        $data   = substr($data, $this->config['iv_size']);

        return rtrim(mcrypt_decrypt($this->config['cipher'], $this->config['key'], $data, $this->config['mode'], $iv), "\0");
    }

}